/*-----------------------------------------------------------------------------
		   Licensed to the Apache Software Foundation (ASF) under one
           or more contributor license agreements.  See the NOTICE file
           distributed with this work for additional information
           regarding copyright ownership.  The ASF licenses this file
           to you under the Apache License, Version 2.0 (the
           "License"); you may not use this file except in compliance
           with the License.  You may obtain a copy of the License at

             http://www.apache.org/licenses/LICENSE-2.0

           Unless required by applicable law or agreed to in writing,
           software distributed under the License is distributed on an
           "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
           KIND, either express or implied.  See the License for the
           specific language governing permissions and limitations
           under the License.  
-----------------------------------------------------------------------------*/

package data;

import java.io.File;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;

/**
 * This class uses a singleton pattern to allow the {@link Normalizer}, 
 * {@link Cyclolizer} and {@link ReportGen} classes to have access to the same
 * set of queues which the files are passed through. The files will move from
 * one queue to the next when the appropriate class is finished working on them.
 * This class makes use of concurrent access and has a progression of completion
 * feature.
 * 
 * @author Kevin.J.Jalbert
 */
public class CurrentTask {

	private static final CurrentTask INSTANCE = new CurrentTask();

	// Concurrent access queues to hold files for the various phases they go through
	public static ConcurrentLinkedQueue<File> normFileQueue = new ConcurrentLinkedQueue<File>();
	public static ConcurrentLinkedQueue<SFile> cycloFileQueue = new ConcurrentLinkedQueue<SFile>();
	public static ConcurrentLinkedQueue<SFile> finishedFilesQueue = new ConcurrentLinkedQueue<SFile>();

	// Atomic variables to keep track of file analysis progression on a byte scale
	static public AtomicLong totalBytes = new AtomicLong(0);
	static public AtomicLong currentBytes = new AtomicLong(0);

	/**
	 * Private constructor prevents instantiation from other classes
	 */
	private CurrentTask() {
	}

	/**
	 * Gets the singleton instance of CurrentTask.
	 * 
	 * @return INSTANCE the instance of CurrentTask
	 */
	public static CurrentTask getInstance() {
		return INSTANCE;
	}

	/**
	 * Adds the file to the normalization queue.
	 * 
	 * @param file the file to be added
	 */
	synchronized public void addFileToNormQueue(File file){
		normFileQueue.offer(file);
	}

	/**
	 * Checks if the normalization queue is empty.
	 * 
	 * @return true, if normalization queue is empty
	 */
	synchronized public boolean isNormQueueEmpty(){
		return normFileQueue.isEmpty();
	}

	/**
	 * Gets the next file from normalization queue.
	 * 
	 * @return the next file from queue
	 */
	synchronized public File getFileFromNormQueue() {
		// Get a file to work on
		return normFileQueue.poll();
	}

	/**
	 * Adds the {@link SFile to the cyclomatic queue.
	 * 
	 * @param file the {@link SFile} to be added to the queue
	 */
	synchronized public void addFileToCycloQueue(SFile file){
		cycloFileQueue.offer(file);
	}

	/**
	 * Checks if the cyclomatic queue is empty.
	 * 
	 * @return true, if cyclomatic queue is empty
	 */
	synchronized public boolean isCycloQueueEmpty(){
		return cycloFileQueue.isEmpty();
	}

	/**
	 * Gets the next {@link SFile} from the cyclomatic queue.
	 * 
	 * @return the next {@link SFile} from the queue
	 */
	synchronized public SFile getFileFromCycloQueue() {
		return cycloFileQueue.poll();
	}

	/**
	 * Add the finished {@link SFile} to the finished queue and update the progression.
	 * 
	 * @param file the finished {@link SFile} to the queue
	 */
	synchronized public void fileFinished(SFile file){
		currentBytes.addAndGet((long) file.getFileSize());
		finishedFilesQueue.offer(file);
		printCompletion();
	}

	/**
	 * Prints the current progression of completion based on total and current
	 * bytes of files finished.
	 */
	private void printCompletion() {
		float completion = (float) currentBytes.get() / (float) totalBytes.get() * 100;
		System.out.println(completion);
	}
}